﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.Entity;
using System.Data.Entity.Validation;
using System.Diagnostics;

using BestEasy.Core;


namespace BestEasy.Data.Ef
{
    public class EfRepositoryBase<T, TId> where T : EfEntityBase
    {
        private readonly IDbContext _context;
        private IDbSet<T> _entities;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="context">Object context</param>
        public EfRepositoryBase(IDbContext context)
        {
            _context = context;
        }

        protected virtual IDbSet<T> Entities
        {
            get
            {
                if (_entities == null)
                    _entities = _context.Set<T>();
                return _entities;
            }
        }

        public  IQueryable<T> Table
        {
            get
            {
                return Entities;
            }
        }

        public IQueryable<T> TableNoTracking
        {
            get
            {
                return Entities.AsNoTracking();
            }
        }

        public int Delete(TId id)
        {
            throw new NotImplementedException();
        }

        public void Delete(T entity)
        {
            try
            {
                if (entity == null)
                    throw new ArgumentNullException("entity");

                Entities.Remove(entity);
                //_context.SaveChanges();
            }
            catch (DbEntityValidationException dbEx)
            {
                var msg = dbEx.EntityValidationErrors.SelectMany(validationErrors => validationErrors.ValidationErrors).Aggregate(string.Empty, (current, validationError) => current + (string.Format("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage) + Environment.NewLine));

                var fail = new Exception(msg, dbEx);
                Debug.WriteLine(fail.Message, fail);
                throw fail;
            }
        }

        public T GetById(TId id)
        {
            return Entities.Find(id);
        }

        public void Insert(T entity)
        {
            try
            {
                if (entity == null)
                    throw new ArgumentNullException("entity");

                Entities.Add(entity);

                //_context.SaveChanges();
            }
            catch (DbEntityValidationException dbEx)
            {
                var msg = dbEx.EntityValidationErrors.SelectMany(
                    validationErrors => validationErrors.ValidationErrors).Aggregate(string.Empty, 
                    (current, validationError) => current + (string.Format("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage) + Environment.NewLine));

                var fail = new Exception(msg, dbEx);
                Debug.WriteLine(fail.Message, fail);
                throw fail;
            }
        }

        public void InsertBulk(IEnumerable<T> entitys)
        {
            try
            {
                if (entitys == null)
                    throw new ArgumentNullException("entitys");

                entitys.ToList().ForEach(p => { Entities.Add(p); });
                //_context.SaveChanges();
            }
            catch (DbEntityValidationException dbEx)
            {
                var msg = dbEx.EntityValidationErrors.SelectMany(validationErrors => validationErrors.ValidationErrors).Aggregate(string.Empty, (current, validationError) => current + (string.Format("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage) + Environment.NewLine));

                var fail = new Exception(msg, dbEx);
                Debug.WriteLine(fail.Message, fail);
                throw fail;
            }
        }

        public void Update(T entity)
        {
            try
            {
                if (entity == null)
                    throw new ArgumentNullException("entity");

                _context.SaveChanges();
            }
            catch (DbEntityValidationException dbEx)
            {
                var msg = dbEx.EntityValidationErrors.SelectMany(validationErrors => validationErrors.ValidationErrors).Aggregate(string.Empty, (current, validationError) => current + (string.Format("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage) + Environment.NewLine));

                var fail = new Exception(msg, dbEx);
                Debug.WriteLine(fail.Message, fail);
                throw fail;
            }
        }

        public void UpdateBulk(IEnumerable<T> entitys)
        {
            try
            {
                if (entitys == null)
                    throw new ArgumentNullException("entitys");
                _context.SaveChanges();
            }
            catch (DbEntityValidationException dbEx)
            {
                var msg = dbEx.EntityValidationErrors.SelectMany(validationErrors => validationErrors.ValidationErrors).Aggregate(string.Empty, (current, validationError) => current + (string.Format("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage) + Environment.NewLine));

                var fail = new Exception(msg, dbEx);
                Debug.WriteLine(fail.Message, fail);
                throw fail;
            }
        }
    }
}
